1# Migrating [Universal Modules][universal-modules] to TypeScript
2
3- [Change Import](#change-import)
4- [Testing](#testing)
5  - [Add the tests to CI](#add-the-tests-to-ci)
6- [Move native `dependencies` to `peerDependencies`](#move-native--dependencies--to--peerdependencies-)
7- [Add module scripts](#add-module-scripts)
8- [Generate a `tsconfig.json` file with `expo-module-scripts`](#generate-a--tsconfigjson--file-with--expo-module-scripts-)
9- [Various Other Changes](#various-other-changes)
10
11## Change Import
12
13To optimize our libraries for _dead code elimination_ we should migrate our exports to be imported as such:
14
15```diff
16
17- import { FileSystem } from 'expo-file-system';
18
19+ import * as FileSystem from 'expo-file-system';
20
21```
22
23Ideally we would make the main entry-point of a module be a file named like the module like `build/FileSystem.js`
24
25**`package.json`**
26
27```diff
28- "main": "index.js",
29
30+ "main": "build/<MODULE NAME>.js",
31+ "types": "build/<MODULE NAME>.d.ts",
32```
33
34To migrate from libraries using different imports, we should add a deprecation notice.
35
36> A lot of libraries are just import from Expo, in these cases we can just the deprecation. Ensure you change all imports across `packages/`, `apps/`, and `docs/`.
37
38**`src/index.ts`**
39
40```ts
41import * as FileSystem from './FileSystem';
42export * from './FileSystem';
43
44let wasImportWarningShown = false;
45// @ts-ignore: Temporarily define an export named "FileSystem" for legacy compatibility
46Object.defineProperty(exports, 'FileSystem', {
47  get() {
48    if (!wasImportWarningShown) {
49      console.warn(
50        `The syntax "import { FileSystem } from 'expo-file-system'" is deprecated. Use "import * as FileSystem from 'expo-file-system'" or import named exports instead. Support for the old syntax will be removed in SDK 34.`
51      );
52      wasImportWarningShown = true;
53    }
54    return FileSystem;
55  },
56});
57```
58
59Then eventually remove the index in favor of the named file. (`src/FileSystem.ts`)
60
61## Testing
62
63Migration should include the addition of a `src/__tests__` which can be run with `yarn test` in the root directory of the package.
64
651. If the package is using the old structure of `test/` for utilities, they should migrate to using `jest-expo`.
66
67**`src/__tests__/<MODULE NAME>-test.ts`**
68
69```diff
70- import { mockPlatformWeb } from '../../test/mocking';
71
72+ import { mockPlatformWeb } from 'jest-expo';
73```
74
752. Add a jest object to the `package.json`
76
77**`package.json`**
78
79```js
80"jest": {
81  "preset": "expo-module-scripts"
82},
83```
84
853. Run `yarn test` to run the tests.
86
87### Add the tests to CI
88
89In the root `.circleci/config.yaml` add a step to the job named `expo_sdk`. This should be in alphabetic order with the other testing steps.
90
91**`.circleci/config.yaml`**
92
93```yaml
94- yarn:
95    command: test --maxWorkers 1
96    working_directory: ~/expo/packages/expo-sms
97```
98
99## Move native `dependencies` to `peerDependencies`
100
101In order to prevent overlapping native code in `node_modules`, we should move any `dependencies` containing native code to `peerDependencies`.
102
103## Add module scripts
104
105**`package.json`**
106
107```js
108"scripts": {
109    "build": "expo-module build",
110    "clean": "expo-module clean",
111    "test": "expo-module test",
112    "prepare": "expo-module prepare",
113    "prepublishOnly": "expo-module prepublishOnly",
114    "expo-module": "expo-module"
115}
116```
117
118## Generate a `tsconfig.json` file with `expo-module-scripts`
119
120To get the `tsconfig` that we use in all of our modules, run `expo-module prepare` or the yarn script `yarn prepare` (given the script is defined in a module's `package.json`)
121
122**`/tsconfig.json`**
123
124```json
125// @generated by expo-module-scripts
126{
127  "extends": "expo-module-scripts/tsconfig.base",
128  "compilerOptions": {
129    "outDir": "./build"
130  },
131  "include": ["./src"],
132  "exclude": ["**/__mocks__/*", "**/__tests__/*"]
133}
134```
135
136## Various Other Changes
137
138- Remove `babel-preset-expo`
139- Remove `flow`
140- For reusing types across the web implementation's native layer and API layer, types should be moved to a named file with the `.types.ts` extension. There are cases (`expo-av` for example) where you should separate types into smaller files.
141
142[universal-modules]: https://github.com/expo/expo/blob/master/guides/Expo%20Universal%20Module%20Infrastructure.md
143